package net.blank.ui.core
{
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	
	import net.blank.bitmapOperation.BitmapDraw;
	import net.blank.functionUtl.FunctionBinder;
	import net.blank.ui.SystemManager;
	import net.blank.ui.Tip;
	
	/**
	 * 派生自 UIComponent 对象的 大小(width,height) 属性被改变时派发
	 */
	[Event(name="resize", type="ui.core.UIEvent")]
	
	/**
	 * 派生自 UIComponent 对象的 位置(x,y) 属性被改变时派发
	 */
	[Event(name="move", type="ui.core.UIEvent")]
	
	/**
	 * UI组件的基类
	 * @author blank
	 * 
	 */
	public class UIComponent extends InteractiveUI
	{
		/**
		 * 系统管理器
		 */
		protected static const sysMgt:SystemManager=SystemManager.getInstance();
		
		/**
		 * x坐标
		 */
		protected var _x:Number;
		
		/**
		 * y坐标
		 */
		protected var _y:Number;
		
		/**
		 * 宽
		 */
		protected var _width:Number;
		
		/**
		 * 高
		 */
		protected var _height:Number;
		
		/**
		 * 相对定位,到父对象左边的距离
		 */
		protected var _left:Number;
		
		/**
		 * 相对定位,到父对象上边的距离
		 */
		protected var _top:Number;
		
		/**
		 * 相对定位,到父对象右边的距离
		 */
		protected var _right:Number;
		
		/**
		 * 相对定位,到父对象下边的距离
		 */
		protected var _bottom:Number;
		
		/**
		 * 背景图像绘制区域(仅在绘制时,将 _width 和 _height 变量存储到 width 和 height 属性中,以提高性能)
		 */
		protected var $drawRect:Rectangle;
		
		/**
		 * 皮肤
		 */
		protected var _skin:*;
		
		/**
		 * 是否显示背景
		 */
		private var _isShowBackGround:Boolean;
		
		/**
		 * 存储除去 disabled 值为 false 时添加的禁用状态滤镜之外的其它滤镜
		 */
		private var _filters:Array;
		
		/**
		 * 工具提示
		 */
		private var _toolTip:*;
		
		/**
		 * 是否需要更新坐标
		 */
		protected var isNeedUpdateCoordinate:Boolean;
		
		/**
		 * 需要更新背景
		 */
		protected var isNeedUpdateBackground:Boolean;
		
		/**
		 * 需要更新滤镜
		 */
		protected var isNeedUpateFilters:Boolean;
		
		override protected function update():void{
			/*设置坐标*/
			if(isNeedUpdateCoordinate){
				super.x=_x;
				super.y=_y;
				
				isNeedUpdateCoordinate=false;
			}
			
			/*绘制背景*/
			if(isNeedUpdateBackground){
				graphics.clear();
				
				if(_isShowBackGround && _skin && _skin.getBackground() && _width > 0 && _height > 0){
					$drawRect.width=_width;
					$drawRect.height=_height;
					
					if(_skin.getInnerScaleRect()){
						BitmapDraw.drawForClips(graphics,$drawRect,_skin.clipCache);
					}else{
						BitmapDraw.drawBitmap(graphics,_skin.getBackground(),$drawRect);
					}
				}
				
				isNeedUpdateBackground=false;
			}
			
			/*设置滤镜*/
			if(isNeedUpateFilters){
				if(!enabled && _skin && _skin.getDisabledFilters()){
					if(_filters){
						super.filters=_filters.concat(_skin.getDisabledFilters());
					}else{
						super.filters=_skin.getDisabledFilters();
					}
				}else{
					super.filters=_filters;
				}
				
				isNeedUpateFilters=false;
			}
		}
		
		/**
		 * 更新坐标
		 * 
		 */
		protected function updateCoordinate():void{
			if(!isNeedUpdateCoordinate){
				isNeedUpdateCoordinate=true;
				invalidate();
			}
		}
		
		/**
		 * 更新背景
		 * 
		 */
		protected function updateBackground():void{
			if(!isNeedUpdateBackground){
				isNeedUpdateBackground=true;
				invalidate();
			}
		}
		
		/**
		 * 更新滤镜
		 * 
		 */
		protected function updateFilters():void{
			if(!isNeedUpateFilters){
				isNeedUpateFilters=true;
				invalidate();
			}
		}
		
		/**
		 * enabled 状态发生改变(启用/禁用)
		 * @param evt
		 * 
		 */
		protected function enabledChangeHandler(evt:InteractiveUIEvent):void{
			updateFilters();
		}
		
		/**
		 * 鼠标进入,显示 toolTip 文本框.toolTip 属性中有内容时才会被添加此侦听
		 * @param evt
		 * 
		 */
		protected function rollOverHandler(evt:MouseEvent):void{
			Tip.showAny(_toolTip,this);
		}
		
		/**
		 * 父对象的大小发生改变,更新相对定位
		 * @param evt
		 * 
		 */
		private function parent_resizeHandler(evt:UIEvent=null):void{
			if(!isNaN(_right)){
				if(isNaN(_left)){
					_x=parent.width-_right-_width;
					
					updateCoordinate();
					
					dispatchEvent(new UIEvent(UIEvent.MOVE));
				}else{
					_width=parent.width-_left-_right;
					
					updateBackground();
					
					dispatchEvent(new UIEvent(UIEvent.RESIZE));
				}
			}
			
			if(!isNaN(_bottom)){
				if(isNaN(_top)){
					_y=parent.height-_bottom-_height;
					
					updateCoordinate();
					
					dispatchEvent(new UIEvent(UIEvent.MOVE));
				}else{
					_height=parent.height-_top-_bottom;
					
					updateBackground();
					
					dispatchEvent(new UIEvent(UIEvent.RESIZE));
				}
			}
		}
		
		/**
		 * 被添加到父对象
		 * @param evt
		 * 
		 */
		private function addedHandler(evt:Event):void{
			parent_resizeHandler();
			if(parent is UIComponent){
				parent.addEventListener(UIEvent.RESIZE,parent_resizeHandler);
			}
		}
		
		/**
		 * 被坐父对象删除
		 * @param evt
		 * 
		 */
		private function removedHandler(evt:Event):void{
			if(parent is UIComponent){
				parent.removeEventListener(UIEvent.RESIZE,parent_resizeHandler);
			}
		}
		
		/**
		 * UI组件的基类
		 * 
		 */
		public function UIComponent(){
			$drawRect=new Rectangle();
			
			super();
			
			addEventListener(InteractiveUIEvent.ENABLED,enabledChangeHandler);
			addEventListener(InteractiveUIEvent.DISABLED,enabledChangeHandler);
			
			addEventListener(Event.ADDED,addedHandler);
			addEventListener(Event.REMOVED,removedHandler);
		}
		
		/**
		 * 皮肤的背景发生改变,更新背景
		 * @param bmp
		 * 
		 */
		protected function skin_changedBackground():void{
			updateBackground();
		}
		
		/**
		 * 皮肤的9格缩放区域发生改变,更新背景
		 * @param rect
		 * 
		 */
		protected function skin_changedInnerScaleRect():void{
			updateBackground();
		}
		
		/**
		 * 皮肤的禁用状态滤镜发生改变,如果当前是在禁用状态,则更新滤镜
		 * @param filters
		 * 
		 */
		protected function skin_changedDisabledFilters():void{
			if(!enabled){
				updateFilters();
			}
		}
		
		/**
		 * 绑定皮肤
		 * 
		 */
		protected function bindingSkin():void{
			FunctionBinder.addBindingFun(_skin.setBackground,skin_changedBackground);
			FunctionBinder.addBindingFun(_skin.setInnerScaleRect,skin_changedInnerScaleRect);
			FunctionBinder.addBindingFun(_skin.setDisabledFilters,skin_changedDisabledFilters);
		}
		
		/**
		 * 解除对皮肤的绑定
		 * 
		 */
		protected function unbindingSkin():void{
			FunctionBinder.rmBindingFun(_skin.setBackground,skin_changedBackground);
			FunctionBinder.rmBindingFun(_skin.setInnerScaleRect,skin_changedInnerScaleRect);
			FunctionBinder.rmBindingFun(_skin.setDisabledFilters,skin_changedDisabledFilters);
		}
		
		/**
		 * 皮肤
		 */
		public function set skin(value:*):void{
			if(value != _skin){
				if(_skin){
					unbindingSkin();
				}
				_skin=value;
				if(_skin){
					bindingSkin();
				}
				
				updateBackground();
				if(!enabled){
					updateFilters();
				}
			}
		}
		public function get skin():*{
			return _skin;
		}
		
		/**
		 * 是否显示背景
		 * @param value
		 * 
		 */
		public function set showBackGround(value:Boolean):void{
			if(value != _isShowBackGround){
				_isShowBackGround = value;
				
				updateBackground();
			}
		}
		public function get showBackGround():Boolean{
			return _isShowBackGround;
		}
		
		/**
		 * 工具提示
		 * <table>
		 * 	<tr>
		 * 		<th>类型</th>
		 * 		<th>说明</th>
		 * 	</tr>
		 * 	<tr>
		 * 		<td>DisplayObject</td>
		 * 		<td>自定义 tip 显示对象</td>
		 * 	</tr>
		 * 	<tr>
		 * 		<td>String</td>
		 * 		<td>纯文本tip,背景为默认颜色 0xffffff , 字体格式为系统中的默认字体格式</td>
		 * 	</tr>
		 * 	<tr>
		 * 		<td>Array</td>
		 * 		<td>
		 * 			第一个元素的类型须是 String 类型,则各元素的表示如下:<br/>
		 * 			<table>
		 * 				<tr>
		 * 					<th>元素编号</th><th>说明</th>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>0</td><td>String,纯文本tip</td>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>1</td><td>TextFormat/StyleSheet/String,CSS样式表,可选,默认为 null</td>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>2</td><td>Boolean/String,是否显示背景,空字符串(null,"")将被转换为 false ,可选,默认为 true</td>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>3</td><td>uint/String ,背景色,十六进制颜色值的字符串须以 0x 开头,可选,默认为 oxffffff</td>
		 * 				</tr>
		 * 			</table>
		 * 		</td>
		 * 	</tr>
		 * 	<tr>
		 * 		<td>Vector.&lt;String&gt;</td>
		 * 		<td>各元素的说明基本同上(Array)</td>
		 * 	</tr>
		 * 	<tr>
		 * 		<td>Object</td>
		 * 		<td>
		 * 			任意对象都可以,但须具备以下属性
		 * 			<table>
		 * 				<tr>
		 * 					<th>属性名</th>
		 * 					<th>说明</th>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>text</td>
		 * 					<td>String,纯文本tip</td>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>textFormat</td>
		 * 					<td>TextFormat,字体格式</td>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>css</td>
		 * 					<td>String,CSS样式表,可选,默认为 null</td>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>background</td>
		 * 					<td>Boolean,是否显示背景,可选,默认为 true</td>
		 * 				</tr>
		 * 				<tr>
		 * 					<td>backgroundColor</td>
		 * 					<td>String/uint,背景色,十六进制颜色值的字符串须以 0x 开头,可选,默认为 oxffffff</td>
		 * 				</tr>
		 * 			</table>
		 * 		</td>
		 * 	</tr>
		 * </table>
		 * 
		 */
		public function set toolTip(value:*):void{
			if(value != _toolTip){
				if(_toolTip){
					removeEventListener(MouseEvent.ROLL_OVER,rollOverHandler);
				}
				_toolTip=value;
				if(_toolTip){
					addEventListenerIgnoreEnabledState(MouseEvent.ROLL_OVER,rollOverHandler);
				}
			}
		}
		public function get toolTip():*{
			return _toolTip;
		}
		
		/**
		 * x坐标,会清除相对定位的 left 的值
		 * @param value
		 * 
		 */
		override public function set x(value:Number):void{
			if(value != x){
				_x=value;
				updateCoordinate();
				
				if(!isNaN(_right) && parent){
					_width=parent.width-value-_right;/*如果相对右定位仍在,则重新计算宽度*/
					
					updateBackground();
					
					dispatchEvent(new UIEvent(UIEvent.RESIZE));
				}
				
				_left=NaN;/*解除相对左定位*/
				
				dispatchEvent(new UIEvent(UIEvent.MOVE));
			}
		}
		override public function get x():Number{
			return _x;
		}
		
		/**
		 * 相对定位,到父对象左边的距离
		 * @param value
		 * 
		 */
		public function set left(value:Number):void{
			if(value != _left){
				_left=value;
				
				if(!isNaN(value) && parent){
					if(!isNaN(_right)){
						_width=parent.width-value-_right;/*相对左右定位*/
						
						updateBackground();
						
						dispatchEvent(new UIEvent(UIEvent.RESIZE));
					}
				}
				
				_x=value;/*相对左定位*/
				updateCoordinate();
				
				dispatchEvent(new UIEvent(UIEvent.MOVE));
			}
		}
		public function get left():Number{
			return _left;
		}
		
		/**
		 * 相对定位,到父对象右边的距离
		 * @param value
		 * 
		 */
		public function set right(value:Number):void{
			if(value != _right){
				_right=value;
				
				if(!isNaN(value) && parent){
					if(isNaN(_left)){
						_x=parent.width-value-_width;/*相对右定位*/
						
						updateCoordinate();
						
						dispatchEvent(new UIEvent(UIEvent.MOVE));
					}else{
						_width=parent.width-_left-value;/*相对左右定位*/
						
						updateBackground();
						
						dispatchEvent(new UIEvent(UIEvent.RESIZE));
					}
				}
			}
		}
		public function get right():Number{
			return _right;
		}
		
		/**
		 * 宽,如果同时指定了相对定位的 left 和 right,则会清除 right 的值
		 */
		override public function set width(value:Number):void{
			if(value != _width){
				_width=value;
				
				if(!isNaN(_right)){
					if(isNaN(_left)){
						if(parent){
							_x=parent.width-_right-value;/*相对于右定位*/
							
							updateCoordinate();
							
							dispatchEvent(new UIEvent(UIEvent.MOVE));
						}
					}else{
						_right=NaN;/*相对于左右定位,解除相对于右定位*/
					}
				}
				
				updateBackground();
				
				dispatchEvent(new UIEvent(UIEvent.RESIZE));
			}
		}
		
		override public function get width():Number{
			return _width;
		}
		
		/**
		 * y坐标,会清除相对定位的 top 的值
		 * @param value
		 * 
		 */
		override public function set y(value:Number):void{
			if(value != y){
				_y=value;
				updateCoordinate();
				
				if(!isNaN(_bottom) && parent){
					_height=parent.height-value-_bottom;/*如果相对下定位仍在,则重新计算高度*/
					
					updateBackground();
					
					dispatchEvent(new UIEvent(UIEvent.RESIZE));
				}
				
				_top=NaN;/*解除相对上定位*/
				
				dispatchEvent(new UIEvent(UIEvent.MOVE));
			}
		}
		override public function get y():Number{
			return _y;
		}
		
		/**
		 * 相对定位,到父对象上边的距离
		 * @param value
		 * 
		 */
		public function set top(value:Number):void{
			if(value != _top){
				_top=value;
				
				if(!isNaN(value) && parent){
					if(!isNaN(_bottom)){
						_height=parent.height-value-_bottom;/*相对上下定位*/
						
						updateBackground();
						
						dispatchEvent(new UIEvent(UIEvent.RESIZE));
					}
				}
				
				_y=value;/*相对上定位*/
				updateCoordinate();
				
				dispatchEvent(new UIEvent(UIEvent.MOVE));
			}
		}
		public function get top():Number{
			return _top;
		}
		
		/**
		 * 相对定位,到父对象下边的距离
		 * @param value
		 * 
		 */
		public function set bottom(value:Number):void{
			if(value != _bottom){
				_bottom=value;
				
				if(!isNaN(value) && parent){
					if(isNaN(_top)){
						_y=parent.height-value-_height;/*相对下定位*/
						
						updateCoordinate();
						
						dispatchEvent(new UIEvent(UIEvent.MOVE));
					}else{
						_height=parent.height-_top-value;/*相对上下定位*/
						
						updateBackground();
						
						dispatchEvent(new UIEvent(UIEvent.RESIZE));
					}
				}
			}
		}
		public function get bottom():Number{
			return _bottom;
		}
		
		/**
		 * 高,如果同时指定了相对定位的 top 和 bottom,则会清除 bottom 的值
		 */
		override public function set height(value:Number):void{
			if(value != _height){
				_height=value;
				
				if(!isNaN(_bottom)){
					if(isNaN(_top)){
						if(parent){
							_y=parent.height-_bottom-value;/*相对于下定位*/
							
							updateCoordinate();
							
							dispatchEvent(new UIEvent(UIEvent.MOVE));
						}
					}else{
						_bottom=NaN;/*相对于上下定位,解除相对于下定位*/
					}
				}
				
				updateBackground();
				
				dispatchEvent(new UIEvent(UIEvent.RESIZE));
			}
		}
		override public function get height():Number{
			return _height;
		}
		
		override public function set filters(value:Array):void{
			if(value != _filters){
				_filters=value;
				
				updateFilters();
			}
		}
		override public function get filters():Array{
			return _filters;
		}
		
		override public function destroy():void{
			removeEventListener(InteractiveUIEvent.ENABLED,enabledChangeHandler);
			removeEventListener(InteractiveUIEvent.DISABLED,enabledChangeHandler);
			
			removeEventListener(Event.ADDED,addedHandler);
			removeEventListener(Event.REMOVED,removedHandler);
			
			if(_skin){
				unbindingSkin();
			}
			_skin=null;
			_filters=null;
			$drawRect=null;
			
			super.destroy();
		}
		
		override public function reset():void{
			_isShowBackGround=true;
			
			if(_skin){
				unbindingSkin();
			}
			skin=null;
			filters=null;
			
			_x=_y=0;
			_left=_right=_top=_bottom=NaN;
			
			_width=_height=0;
			graphics.clear();
			
			super.reset();
		}
		
		/**
		 * x 坐标,无渲染延迟
		 * @param value
		 * 
		 */
		noRenderDelay function set x(value:Number):void{
			super.x=value;
		}
		/**
		 * 无渲染延迟的真实 x 坐标
		 * @return 
		 * 
		 */
		noRenderDelay function get x():Number{
			return super.x;
		}
		
		/**
		 * y 坐标,无渲染延迟
		 * @param value
		 * 
		 */
		noRenderDelay function set y(value:Number):void{
			super.y=value;
		}
		/**
		 * 无渲染延迟的真实 y 坐标
		 * @return 
		 * 
		 */
		noRenderDelay function get y():Number{
			return super.y;
		}
		
		/**
		 * 滤镜,无渲染延迟
		 * @param value
		 * 
		 */
		noRenderDelay function set filters(value:Array):void{
			super.filters=value;
		}
		/**
		 * 无渲染延迟的真实滤镜
		 * @return 
		 * 
		 */
		noRenderDelay function get filters():Array{
			return super.filters;
		}
	}
}